#include "../corelib/util/consistent_hashing.hh"
#include "unittest/unittest.hh"
#include <string>

using namespace kratos::corelib;

FIXTURE_BEGIN(ConsistentHashing)

std::uint32_t myHash(const std::string& s) {
    std::uint32_t v = 0;
    for (auto c : s) {
        if (isdigit(c)) {
            v += (std::uint32_t)(c - '0');
        } else {
            v += (std::uint32_t)c;
        }
    }
    return v;
}

CASE(TestStart) {
    ConsistentHash hash;
    ASSERT_TRUE(hash.start());
    ASSERT_TRUE(hash.start());
}

CASE(TestAddNode) {
    ConsistentHash hash;
    ASSERT_TRUE(hash.start());
    ASSERT_FALSE(hash.addNode("", 1));
    ASSERT_TRUE(hash.addNode("server", 1));
    ASSERT_TRUE(hash.getVNodeCount("server") == 32);
    ASSERT_TRUE(hash.getVNodeCount("sever") == 0);
}

CASE(TestRemoveNode) {
    ConsistentHash hash;
    ASSERT_TRUE(hash.start());
    ASSERT_TRUE(hash.addNode("server", 1));
    ASSERT_TRUE(hash.removeNode("server"));
    ASSERT_TRUE(hash.getVNodeCount("server") == 0);
}

CASE(TestGetNode) {
    ConsistentHash hash;
    ASSERT_TRUE(hash.start());
    ASSERT_TRUE(hash.addNode("server", 1));
    ASSERT_TRUE(hash.addNode("server2", 2));
    ASSERT_TRUE(hash.getNode(132488991) != 0);
}

CASE(TestRehash) {
    ConsistentHash hash;
    std::uint64_t o = 0;
    std::uint64_t n = 0;
    int count = 0;
    hash.start(
        [&](std::uint64_t oldNode, std::uint64_t newNode) {
            o = oldNode;
            n = newNode;
            count += 1;
        },
        myHash);
    hash.addNode("server", 1, 10);
    ASSERT_TRUE(count == 10);
    ASSERT_TRUE((o == 0) && (n == 1));
}

FIXTURE_END(ConsistentHashing)
